// Copyright 2021 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Author: Matteo Perotti <mperotti@iis.ee.ethz.ch>

#include "vector_macros.h"

#define AXI_DWIDTH_MAX 512
#define MEM_VEC_SIZE 64

#define MEM_VCLEAR(vec)                                                        \
  {                                                                            \
    for (int i = 0; i < MEM_VEC_SIZE; ++i)                                     \
      vec[i] = 0;                                                              \
  }

static volatile uint8_t ALIGNED_O8[MEM_VEC_SIZE]
    __attribute__((aligned(AXI_DWIDTH_MAX))) = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static volatile uint16_t ALIGNED_O16[MEM_VEC_SIZE]
    __attribute__((aligned(AXI_DWIDTH_MAX))) = {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};

static volatile uint32_t ALIGNED_O32[MEM_VEC_SIZE]
    __attribute__((aligned(AXI_DWIDTH_MAX))) = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000};

static volatile uint64_t ALIGNED_O64[MEM_VEC_SIZE]
    __attribute__((aligned(AXI_DWIDTH_MAX))) = {
        0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
        0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
        0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
        0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
        0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
        0x0000000000000000};

int stride;

// Segment-2
void TEST_CASE1_8(void) {

  VSET(-1, e8, m1);
  volatile uint8_t INP1[] = {
      0x9f, 0xe4, 0x19, 0x20, 0x8f, 0x2e, 0x05, 0xe0, 0xf9, 0xaa, 0x71,
      0xf0, 0xc3, 0x94, 0xbb, 0xd3, 0x31, 0x4a, 0x57, 0x6b, 0x83, 0x7d,
      0x1a, 0x45, 0xb2, 0xda, 0x22, 0x56, 0x63, 0x8c, 0xf7, 0x3e, 0x6c,
      0x27, 0x74, 0x9d, 0xab, 0xcd, 0x13, 0x38, 0x5e, 0x42, 0xdf, 0x80,
      0x60, 0xa4, 0x7b, 0x0b, 0xc6, 0xad, 0x91, 0xec, 0x3c, 0x69, 0xf5,
      0x18, 0xe8, 0x6d, 0xb9, 0x82, 0x97, 0x2a, 0x51, 0x70};
  VCLEAR(v1);
  VCLEAR(v2);
  stride = 0;
  VSET(5, e8, m1);
  asm volatile("vlsseg2e8.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg2e8.v v1, (%0), %1" ::"r"(ALIGNED_O8), "r"(stride));
  VVCMP_U8(1, ALIGNED_O8, 0x9f, 0xe4, 0, 0, 0, 0, 0, 0);

  MEM_VCLEAR(ALIGNED_O8);
  VCLEAR(v1);
  VCLEAR(v2);
  stride = 2;
  VSET(32, e8, m1);
  asm volatile("vlsseg2e8.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg2e8.v v1, (%0), %1" ::"r"(ALIGNED_O8), "r"(stride));
  VVCMP_U8(2, ALIGNED_O8, 0x9f, 0xe4, 0x19, 0x20, 0x8f, 0x2e, 0x05, 0xe0, 0xf9,
           0xaa, 0x71, 0xf0, 0xc3, 0x94, 0xbb, 0xd3, 0x31, 0x4a, 0x57, 0x6b,
           0x83, 0x7d, 0x1a, 0x45, 0xb2, 0xda, 0x22, 0x56, 0x63, 0x8c, 0xf7,
           0x3e, 0x6c, 0x27, 0x74, 0x9d, 0xab, 0xcd, 0x13, 0x38, 0x5e, 0x42,
           0xdf, 0x80, 0x60, 0xa4, 0x7b, 0x0b, 0xc6, 0xad, 0x91, 0xec, 0x3c,
           0x69, 0xf5, 0x18, 0xe8, 0x6d, 0xb9, 0x82, 0x97, 0x2a, 0x51, 0x70);

  MEM_VCLEAR(ALIGNED_O8);
  VCLEAR(v1);
  VCLEAR(v2);
  stride = 3;
  VSET(22, e8, m1);
  asm volatile("vlsseg2e8.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg2e8.v v1, (%0), %1" ::"r"(ALIGNED_O8), "r"(stride));
  VVCMP_U8(3, ALIGNED_O8, 0x9f, 0xe4, 0, 0x20, 0x8f, 0, 0x05, 0xe0, 0, 0xaa,
           0x71, 0, 0xc3, 0x94, 0, 0xd3, 0x31, 0, 0x57, 0x6b, 0, 0x7d, 0x1a, 0,
           0xb2, 0xda, 0, 0x56, 0x63, 0, 0xf7, 0x3e, 0, 0x27, 0x74, 0, 0xab,
           0xcd, 0, 0x38, 0x5e, 0, 0xdf, 0x80, 0, 0xa4, 0x7b, 0, 0xc6, 0xad, 0,
           0xec, 0x3c, 0, 0xf5, 0x18, 0, 0x6d, 0xb9, 0, 0x97, 0x2a, 0, 0x70);
}

// Segment-3
void TEST_CASE2_8(void) {
  VSET(-1, e8, m1);
  volatile uint8_t INP1[] = {
      0x9f, 0xe4, 0x19, 0x20, 0x8f, 0x2e, 0x05, 0xe0, 0xf9, 0xaa, 0x71,
      0xf0, 0xc3, 0x94, 0xbb, 0xd3, 0x31, 0x4a, 0x57, 0x6b, 0x83, 0x7d,
      0x1a, 0x45, 0xb2, 0xda, 0x22, 0x56, 0x63, 0x8c, 0xf7, 0x3e, 0x6c,
      0x27, 0x74, 0x9d, 0xab, 0xcd, 0x13, 0x38, 0x5e, 0x42, 0xdf, 0x80,
      0x60, 0xa4, 0x7b, 0x0b, 0xc6, 0xad, 0x91, 0xec, 0x3c, 0x69, 0xf5,
      0x18, 0xe8, 0x6d, 0xb9, 0x82, 0x97, 0x2a, 0x51, 0x70};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  stride = 3;
  VSET(22, e8, m1);
  asm volatile("vlsseg3e8.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg3e8.v v1, (%0), %1" ::"r"(ALIGNED_O8), "r"(stride));
  VVCMP_U8(4, ALIGNED_O8, 0x9f, 0xe4, 0x19, 0x20, 0x8f, 0x2e, 0x05, 0xe0, 0xf9,
           0xaa, 0x71, 0xf0, 0xc3, 0x94, 0xbb, 0xd3, 0x31, 0x4a, 0x57, 0x6b,
           0x83, 0x7d, 0x1a, 0x45, 0xb2, 0xda, 0x22, 0x56, 0x63, 0x8c, 0xf7,
           0x3e, 0x6c, 0x27, 0x74, 0x9d, 0xab, 0xcd, 0x13, 0x38, 0x5e, 0x42,
           0xdf, 0x80, 0x60, 0xa4, 0x7b, 0x0b, 0xc6, 0xad, 0x91, 0xec, 0x3c,
           0x69, 0xf5, 0x18, 0xe8, 0x6d, 0xb9, 0x82, 0x97, 0x2a, 0x51, 0x70);
}

// Segment-8
void TEST_CASE4_16(void) {
  VSET(-1, e16, m1);
  volatile uint16_t INP1[] = {
      0x1234, 0x5678, 0x9abc, 0xdef0, 0x1111, 0x2222, 0x3333, 0x4444,
      0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc,
      0xdddd, 0xeeee, 0xffff, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505,
      0x0606, 0x0707, 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d,
      0x0e0e, 0x0f0f, 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515,
      0x1616, 0x1717, 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d,
      0x1e1e, 0x1f1f, 0x2020, 0x2121, 0x2222, 0x2323, 0x2424, 0x2525,
      0x2626, 0x2727, 0x2828, 0x2929, 0x2a2a, 0x2b2b, 0x2c2c, 0x2d2d};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  VCLEAR(v4);
  VCLEAR(v5);
  VCLEAR(v6);
  VCLEAR(v7);
  VCLEAR(v8);
  stride = 16;
  VSET(8, e16, m1);
  asm volatile("vlsseg8e16.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg8e16.v v1, (%0), %1" ::"r"(ALIGNED_O16), "r"(stride));
  VVCMP_U16(5, ALIGNED_O16, 0x1234, 0x5678, 0x9abc, 0xdef0, 0x1111, 0x2222,
            0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa,
            0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff, 0x0101, 0x0202, 0x0303,
            0x0404, 0x0505, 0x0606, 0x0707, 0x0808, 0x0909, 0x0a0a, 0x0b0b,
            0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x1010, 0x1111, 0x1212, 0x1313,
            0x1414, 0x1515, 0x1616, 0x1717, 0x1818, 0x1919, 0x1a1a, 0x1b1b,
            0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f, 0x2020, 0x2121, 0x2222, 0x2323,
            0x2424, 0x2525, 0x2626, 0x2727, 0x2828, 0x2929, 0x2a2a, 0x2b2b,
            0x2c2c, 0x2d2d);
}

// Segment-3
void TEST_CASE2_32(void) {
  VSET(-1, e32, m1);
  volatile uint32_t INP1[] = {
      0xe19afa6b, 0x8c10145c, 0xbca44cc5, 0x11ffa54e, 0x82f92af6, 0x9af29daa,
      0x956eb527, 0x575c2e05, 0x68fb4cc5, 0xcf7a1d98, 0x53a0be4e, 0x26439a12,
      0x785cc853, 0x35659121, 0xf7a96b8c, 0xa87678a2, 0xb11d757e, 0x67dd4037,
      0xd29ad01e, 0xb7600abf, 0x2e572002, 0xaadc6195, 0xcefce71b, 0x64d90d0c,
      0x6c3b54b0, 0xcc6da682, 0xd8b7ae76, 0x8533b185, 0xa2cd798c, 0x2a4339cc,
      0xcf9238fb, 0x7e70281b, 0xdf162ee9, 0x4f2ea60f, 0x4b32bcdd, 0xbf3b8546,
      0x52b26ff5, 0x18cbcecd, 0xc364c8f8, 0x5bf0c67b, 0x60914005, 0x93265d9d,
      0xcff3c77d, 0x788529c3, 0xdda63ceb, 0x4edd7f48, 0xddcd4d07, 0x3266d631,
      0x3b2f25a6, 0x7bfd8a81, 0x9db64ef5, 0xa06a42d4, 0x687f8a39, 0xb9272633,
      0xb009319e, 0xf542d689, 0x45ef05c9, 0xf547c96e, 0x2a143e76, 0x17a38eec,
      0x9a73626c, 0xca064493, 0x582140dd, 0x97df3c7a};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  stride = 12;
  VSET(22, e32, m1);
  asm volatile("vlsseg3e32.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg3e32.v v1, (%0), %1" ::"r"(ALIGNED_O32), "r"(stride));
  VVCMP_U32(
      6, ALIGNED_O32, 0xe19afa6b, 0x8c10145c, 0xbca44cc5, 0x11ffa54e,
      0x82f92af6, 0x9af29daa, 0x956eb527, 0x575c2e05, 0x68fb4cc5, 0xcf7a1d98,
      0x53a0be4e, 0x26439a12, 0x785cc853, 0x35659121, 0xf7a96b8c, 0xa87678a2,
      0xb11d757e, 0x67dd4037, 0xd29ad01e, 0xb7600abf, 0x2e572002, 0xaadc6195,
      0xcefce71b, 0x64d90d0c, 0x6c3b54b0, 0xcc6da682, 0xd8b7ae76, 0x8533b185,
      0xa2cd798c, 0x2a4339cc, 0xcf9238fb, 0x7e70281b, 0xdf162ee9, 0x4f2ea60f,
      0x4b32bcdd, 0xbf3b8546, 0x52b26ff5, 0x18cbcecd, 0xc364c8f8, 0x5bf0c67b,
      0x60914005, 0x93265d9d, 0xcff3c77d, 0x788529c3, 0xdda63ceb, 0x4edd7f48,
      0xddcd4d07, 0x3266d631, 0x3b2f25a6, 0x7bfd8a81, 0x9db64ef5, 0xa06a42d4,
      0x687f8a39, 0xb9272633, 0xb009319e, 0xf542d689, 0x45ef05c9, 0xf547c96e,
      0x2a143e76, 0x17a38eec, 0x9a73626c, 0xca064493, 0x582140dd, 0x97df3c7a);
}

// Segment-2
void TEST_CASE1_64(void) {

  VSET(-1, e64, m1);
  volatile uint64_t INP1[] = {
      0xfa3a99086b4b64aa, 0x57bb4a671118fdc0, 0xbb8df43b65bac0d2,
      0xa41351c301c72b5b, 0x511e175802d24608, 0x64d7a5514d544e52,
      0xbf1d53ca3e3c6bf7, 0xd31ac04eea8ecc07, 0x52edd3cfec205090,
      0x891a1820b423c29c, 0xfc8e3370b171c315, 0xa30da5c56e052f67,
      0x9f79ec1cdf33c0bc, 0x5d2c78d9927dfa33, 0x52b80462b7e072f9,
      0x3e0efee7a99a28e7, 0x3216edfad69d8286, 0x7409095aa2433e2e,
      0x45efda30062c904b, 0x2b707d3fbaef7019, 0xde9483fe82609c40,
      0x9d5e63fed3019ea6, 0xc4bae94e8d757c0f, 0x7c917722900ef4d8,
      0x693f603446fb64e6, 0x42cb1e2132c3d7d5, 0xd77ba2e13e47d589,
      0x45887508688c93b2, 0xac730ac471f57a8e, 0x708ca6623c11c1ff,
      0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba, 0x3adf5823d1051252,
      0xc31b51ef18e6dc16, 0xa96c56ed56947466, 0x5e0f5c76fdd72450,
      0xada6b728b9b84f27, 0x9ef5b07ca6742028, 0x2d52c2213e1497ab,
      0x201b60e0fbbc4acd, 0x5428920ecca684b1, 0xc826aff176ba9a29,
      0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5, 0x8aac4c04213d26aa,
      0xecd584f402152e19, 0x89f5805801f25a66, 0xbad7cab9c4062ffc,
      0xb6715b7275106bc1, 0x53112b0cc2123035, 0x8ec585926ed7af58,
      0xce4722d4b56cd330, 0x14041ab000c9c396, 0x928220385ce8c56d,
      0xdb402f4b0fd38776, 0x180002d7d73b1ae2, 0x76c882042e57f707,
      0xd13e73308658ad1f, 0x5142eb4c19644e7d, 0x23def41d77db2d38,
      0x34affa8555d23fd9, 0xa311951efe71188d, 0xf96089370f7fa0a7,
      0xb0899dfea0b44c26};

  VCLEAR(v1);
  VCLEAR(v2);
  stride = 0;
  VSET(5, e64, m1);
  asm volatile("vlsseg2e64.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg2e64.v v1, (%0), %1" ::"r"(ALIGNED_O64), "r"(stride));
  VVCMP_U64(7, ALIGNED_O64, 0xfa3a99086b4b64aa, 0x57bb4a671118fdc0, 0, 0, 0, 0);

  VSET(-1, e64, m1);
  VCLEAR(v1);
  VCLEAR(v2);
  stride = 16;
  VSET(32, e64, m1);
  asm volatile("vlsseg2e64.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg2e64.v v1, (%0), %1" ::"r"(ALIGNED_O64), "r"(stride));
  VVCMP_U64(8, ALIGNED_O64, 0xfa3a99086b4b64aa, 0x57bb4a671118fdc0,
            0xbb8df43b65bac0d2, 0xa41351c301c72b5b, 0x511e175802d24608,
            0x64d7a5514d544e52, 0xbf1d53ca3e3c6bf7, 0xd31ac04eea8ecc07,
            0x52edd3cfec205090, 0x891a1820b423c29c, 0xfc8e3370b171c315,
            0xa30da5c56e052f67, 0x9f79ec1cdf33c0bc, 0x5d2c78d9927dfa33,
            0x52b80462b7e072f9, 0x3e0efee7a99a28e7, 0x3216edfad69d8286,
            0x7409095aa2433e2e, 0x45efda30062c904b, 0x2b707d3fbaef7019,
            0xde9483fe82609c40, 0x9d5e63fed3019ea6, 0xc4bae94e8d757c0f,
            0x7c917722900ef4d8, 0x693f603446fb64e6, 0x42cb1e2132c3d7d5,
            0xd77ba2e13e47d589, 0x45887508688c93b2, 0xac730ac471f57a8e,
            0x708ca6623c11c1ff, 0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba,
            0x3adf5823d1051252, 0xc31b51ef18e6dc16, 0xa96c56ed56947466,
            0x5e0f5c76fdd72450, 0xada6b728b9b84f27, 0x9ef5b07ca6742028,
            0x2d52c2213e1497ab, 0x201b60e0fbbc4acd, 0x5428920ecca684b1,
            0xc826aff176ba9a29, 0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5,
            0x8aac4c04213d26aa, 0xecd584f402152e19, 0x89f5805801f25a66,
            0xbad7cab9c4062ffc, 0xb6715b7275106bc1, 0x53112b0cc2123035,
            0x8ec585926ed7af58, 0xce4722d4b56cd330, 0x14041ab000c9c396,
            0x928220385ce8c56d, 0xdb402f4b0fd38776, 0x180002d7d73b1ae2,
            0x76c882042e57f707, 0xd13e73308658ad1f, 0x5142eb4c19644e7d,
            0x23def41d77db2d38, 0x34affa8555d23fd9, 0xa311951efe71188d,
            0xf96089370f7fa0a7, 0xb0899dfea0b44c26);
}

// Segment-8
void TEST_CASE4_64(void) {
  VSET(-1, e64, m1);
  volatile uint64_t INP1[] = {
      0xfa3a99086b4b64aa, 0x57bb4a671118fdc0, 0xbb8df43b65bac0d2,
      0xa41351c301c72b5b, 0x511e175802d24608, 0x64d7a5514d544e52,
      0xbf1d53ca3e3c6bf7, 0xd31ac04eea8ecc07, 0x52edd3cfec205090,
      0x891a1820b423c29c, 0xfc8e3370b171c315, 0xa30da5c56e052f67,
      0x9f79ec1cdf33c0bc, 0x5d2c78d9927dfa33, 0x52b80462b7e072f9,
      0x3e0efee7a99a28e7, 0x3216edfad69d8286, 0x7409095aa2433e2e,
      0x45efda30062c904b, 0x2b707d3fbaef7019, 0xde9483fe82609c40,
      0x9d5e63fed3019ea6, 0xc4bae94e8d757c0f, 0x7c917722900ef4d8,
      0x693f603446fb64e6, 0x42cb1e2132c3d7d5, 0xd77ba2e13e47d589,
      0x45887508688c93b2, 0xac730ac471f57a8e, 0x708ca6623c11c1ff,
      0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba, 0x3adf5823d1051252,
      0xc31b51ef18e6dc16, 0xa96c56ed56947466, 0x5e0f5c76fdd72450,
      0xada6b728b9b84f27, 0x9ef5b07ca6742028, 0x2d52c2213e1497ab,
      0x201b60e0fbbc4acd, 0x5428920ecca684b1, 0xc826aff176ba9a29,
      0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5, 0x8aac4c04213d26aa,
      0xecd584f402152e19, 0x89f5805801f25a66, 0xbad7cab9c4062ffc,
      0xb6715b7275106bc1, 0x53112b0cc2123035, 0x8ec585926ed7af58,
      0xce4722d4b56cd330, 0x14041ab000c9c396, 0x928220385ce8c56d,
      0xdb402f4b0fd38776, 0x180002d7d73b1ae2, 0x76c882042e57f707,
      0xd13e73308658ad1f, 0x5142eb4c19644e7d, 0x23def41d77db2d38,
      0x34affa8555d23fd9, 0xa311951efe71188d, 0xf96089370f7fa0a7,
      0xb0899dfea0b44c26};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  VCLEAR(v4);
  VCLEAR(v5);
  VCLEAR(v6);
  VCLEAR(v7);
  VCLEAR(v8);
  stride = 64;
  VSET(8, e64, m1);
  asm volatile("vlsseg8e64.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg8e64.v v1, (%0), %1" ::"r"(ALIGNED_O64), "r"(stride));
  VVCMP_U64(9, ALIGNED_O64, 0xfa3a99086b4b64aa, 0x57bb4a671118fdc0,
            0xbb8df43b65bac0d2, 0xa41351c301c72b5b, 0x511e175802d24608,
            0x64d7a5514d544e52, 0xbf1d53ca3e3c6bf7, 0xd31ac04eea8ecc07,
            0x52edd3cfec205090, 0x891a1820b423c29c, 0xfc8e3370b171c315,
            0xa30da5c56e052f67, 0x9f79ec1cdf33c0bc, 0x5d2c78d9927dfa33,
            0x52b80462b7e072f9, 0x3e0efee7a99a28e7, 0x3216edfad69d8286,
            0x7409095aa2433e2e, 0x45efda30062c904b, 0x2b707d3fbaef7019,
            0xde9483fe82609c40, 0x9d5e63fed3019ea6, 0xc4bae94e8d757c0f,
            0x7c917722900ef4d8, 0x693f603446fb64e6, 0x42cb1e2132c3d7d5,
            0xd77ba2e13e47d589, 0x45887508688c93b2, 0xac730ac471f57a8e,
            0x708ca6623c11c1ff, 0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba,
            0x3adf5823d1051252, 0xc31b51ef18e6dc16, 0xa96c56ed56947466,
            0x5e0f5c76fdd72450, 0xada6b728b9b84f27, 0x9ef5b07ca6742028,
            0x2d52c2213e1497ab, 0x201b60e0fbbc4acd, 0x5428920ecca684b1,
            0xc826aff176ba9a29, 0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5,
            0x8aac4c04213d26aa, 0xecd584f402152e19, 0x89f5805801f25a66,
            0xbad7cab9c4062ffc, 0xb6715b7275106bc1, 0x53112b0cc2123035,
            0x8ec585926ed7af58, 0xce4722d4b56cd330, 0x14041ab000c9c396,
            0x928220385ce8c56d, 0xdb402f4b0fd38776, 0x180002d7d73b1ae2,
            0x76c882042e57f707, 0xd13e73308658ad1f, 0x5142eb4c19644e7d,
            0x23def41d77db2d38, 0x34affa8555d23fd9, 0xa311951efe71188d,
            0xf96089370f7fa0a7, 0xb0899dfea0b44c26);
}

// Segment-3
void TEST_CASE2_8_m(void) {
  VSET(-1, e8, m1);
  volatile uint8_t INP1[] = {
      0x9f, 0xe4, 0x19, 0x20, 0x8f, 0x2e, 0x05, 0xe0, 0xf9, 0xaa, 0x71,
      0xf0, 0xc3, 0x94, 0xbb, 0xd3, 0x31, 0x4a, 0x57, 0x6b, 0x83, 0x7d,
      0x1a, 0x45, 0xb2, 0xda, 0x22, 0x56, 0x63, 0x8c, 0xf7, 0x3e, 0x6c,
      0x27, 0x74, 0x9d, 0xab, 0xcd, 0x13, 0x38, 0x5e, 0x42, 0xdf, 0x80,
      0x60, 0xa4, 0x7b, 0x0b, 0xc6, 0xad, 0x91, 0xec, 0x3c, 0x69, 0xf5,
      0x18, 0xe8, 0x6d, 0xb9, 0x82, 0x97, 0x2a, 0x51, 0x70};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  stride = 3;
  VSET(8, e8, m1);
  VLOAD_8(v0, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA);
  VSET(22, e8, m1);
  asm volatile("vlsseg3e8.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg3e8.v v1, (%0), %1, v0.t" ::"r"(ALIGNED_O8), "r"(stride));
  VVCMP_U8(10, ALIGNED_O8, 0, 0, 0, 0x20, 0x8f, 0x2e, 0, 0, 0, 0xaa, 0x71, 0xf0,
           0, 0, 0, 0xd3, 0x31, 0x4a, 0, 0, 0, 0x7d, 0x1a, 0x45, 0, 0, 0, 0x56,
           0x63, 0x8c, 0, 0, 0, 0x27, 0x74, 0x9d);
}

// Segment-8
void TEST_CASE4_64_m(void) {
  VSET(-1, e64, m1);
  volatile uint64_t INP1[] = {
      0xfa3a99086b4b64aa, 0x57bb4a671118fdc0, 0xbb8df43b65bac0d2,
      0xa41351c301c72b5b, 0x511e175802d24608, 0x64d7a5514d544e52,
      0xbf1d53ca3e3c6bf7, 0xd31ac04eea8ecc07, 0x52edd3cfec205090,
      0x891a1820b423c29c, 0xfc8e3370b171c315, 0xa30da5c56e052f67,
      0x9f79ec1cdf33c0bc, 0x5d2c78d9927dfa33, 0x52b80462b7e072f9,
      0x3e0efee7a99a28e7, 0x3216edfad69d8286, 0x7409095aa2433e2e,
      0x45efda30062c904b, 0x2b707d3fbaef7019, 0xde9483fe82609c40,
      0x9d5e63fed3019ea6, 0xc4bae94e8d757c0f, 0x7c917722900ef4d8,
      0x693f603446fb64e6, 0x42cb1e2132c3d7d5, 0xd77ba2e13e47d589,
      0x45887508688c93b2, 0xac730ac471f57a8e, 0x708ca6623c11c1ff,
      0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba, 0x3adf5823d1051252,
      0xc31b51ef18e6dc16, 0xa96c56ed56947466, 0x5e0f5c76fdd72450,
      0xada6b728b9b84f27, 0x9ef5b07ca6742028, 0x2d52c2213e1497ab,
      0x201b60e0fbbc4acd, 0x5428920ecca684b1, 0xc826aff176ba9a29,
      0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5, 0x8aac4c04213d26aa,
      0xecd584f402152e19, 0x89f5805801f25a66, 0xbad7cab9c4062ffc,
      0xb6715b7275106bc1, 0x53112b0cc2123035, 0x8ec585926ed7af58,
      0xce4722d4b56cd330, 0x14041ab000c9c396, 0x928220385ce8c56d,
      0xdb402f4b0fd38776, 0x180002d7d73b1ae2, 0x76c882042e57f707,
      0xd13e73308658ad1f, 0x5142eb4c19644e7d, 0x23def41d77db2d38,
      0x34affa8555d23fd9, 0xa311951efe71188d, 0xf96089370f7fa0a7,
      0xb0899dfea0b44c26};

  VCLEAR(v1);
  VCLEAR(v2);
  VCLEAR(v3);
  VCLEAR(v4);
  VCLEAR(v5);
  VCLEAR(v6);
  VCLEAR(v7);
  VCLEAR(v8);
  stride = 64;
  VSET(8, e8, m1);
  VLOAD_8(v0, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA);
  VSET(8, e64, m1);
  asm volatile("vlsseg8e64.v v1, (%0), %1" ::"r"(INP1), "r"(stride));
  asm volatile("vssseg8e64.v v1, (%0), %1, v0.t" ::"r"(ALIGNED_O64),
               "r"(stride));
  VVCMP_U64(11, ALIGNED_O64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0x693f603446fb64e6, 0x42cb1e2132c3d7d5,
            0xd77ba2e13e47d589, 0x45887508688c93b2, 0xac730ac471f57a8e,
            0x708ca6623c11c1ff, 0x90c7d0d2a8aa883c, 0xdb0427f14bb4d5ba, 0, 0, 0,
            0, 0, 0, 0, 0, 0x5428920ecca684b1, 0xc826aff176ba9a29,
            0x6f8c8820840f716e, 0x4a2bb5a96b1f24f5, 0x8aac4c04213d26aa,
            0xecd584f402152e19, 0x89f5805801f25a66, 0xbad7cab9c4062ffc, 0, 0, 0,
            0, 0, 0, 0, 0, 0x76c882042e57f707, 0xd13e73308658ad1f,
            0x5142eb4c19644e7d, 0x23def41d77db2d38, 0x34affa8555d23fd9,
            0xa311951efe71188d, 0xf96089370f7fa0a7, 0xb0899dfea0b44c26);
}

int main(void) {
  INIT_CHECK();
  enable_vec();

  TEST_CASE1_8();
  MEM_VCLEAR(ALIGNED_O8);
  TEST_CASE2_8();
  MEM_VCLEAR(ALIGNED_O8);

  TEST_CASE4_16();
  MEM_VCLEAR(ALIGNED_O16);

  TEST_CASE2_32();
  MEM_VCLEAR(ALIGNED_O32);

  TEST_CASE1_64();
  MEM_VCLEAR(ALIGNED_O64);
  TEST_CASE4_64();
  MEM_VCLEAR(ALIGNED_O64);

  // Masked // Todo: fix masked
  //  TEST_CASE2_8_m();
  //  TEST_CASE4_64_m();

  EXIT_CHECK();
}
